#include <stdlib.h>
#include <math.h>
#include <cstdlib>
#include <string>
#include <cstring>
#include "TraceDrivenPowerModel.h"
#include "HSGlobal.h"
#include "../Scheduler/Scheduler.h"
#include "VoltageTrace.h"

TraceDrivenPowerModel::TraceDrivenPowerModel () : PowerModel() {
  // TODO: don't hard-code electrical parameters
  minVoltage = 1.4;
  currentlyDead = false;

  vtrace = new VoltageTrace();
  char const *traceFilename = getenv("HARVSIM_TRACE_FILE");
  if (traceFilename == 0)
    throw std::exception();

  if (vtrace->loadFromFile(traceFilename) < 0)
    throw std::exception();
}

char *TraceDrivenPowerModel::Identify(){
  return (char *)"Trace-Driven Power Model";
}

void TraceDrivenPowerModel::dumpStats(FILE *f){
  HSLOG(f,"Stats for %s\n", this->Identify());
  HSLOG(f,"Final voltage: %1.8f V\n", voltage);
}

PowerModel::QueryResult *TraceDrivenPowerModel::tick(unsigned long currentTick, float powerInWatts){

  return this->queryResult; 

}

PowerModel::QueryResult *TraceDrivenPowerModel::tick(unsigned long currentTick){
  double time = currentTick * Scheduler::tickLengthSeconds;
  voltage = vtrace->getVoltage(time);

  if (this->currentlyDead) {
    if (voltage >= minVoltage) {
      HSLOG(stderr, "Voltage is sufficient again\n");
      this->queryResult->dead = this->currentlyDead = false;
    }
  } else {
    if (voltage < minVoltage) {
      HSLOG(stderr, "Voltage too low; dying\n");
      this->queryResult->dead = this->currentlyDead = true;
    }
  }

  return this->queryResult;
}

TraceDrivenPowerModel::~TraceDrivenPowerModel(){
  delete vtrace;
}

extern "C" PowerModel *Create(){
  return new TraceDrivenPowerModel();
}
